'''
    data_type_yizimi_bit.py
    author: yizimi-yuanxin 
    update: 4.15
'''

# from module_of_msg import exchange_dict, rev_exc_dict
exchange_dict = {
    "string": 0x00000000,
    "Pcapheader": 0xFFFFFFFF,
    "Packetheader": 0xFFFFFFFE,
    "Ethernet_II": 0x00000001,
    "IPv4": 0x00000002,
    "TCP": 0x00000003,
    "UDP": 0x00000004
}

pcap_packet_header_mode = {
    0:          "BSD",          # undefined
    1:          "Ethernet_II",  
    51:         "PPPOE",        # undefined
    105:        "802.11"        # undefined
}
now_pcap_LinkType = ""

BigOrSmall = 0              # 1为小端模式，0为大端模式
							# 一般IP报文以大端模式为主

def list_hex_print(a: list):
    print('[', end='')
    for x in a:
        print(hex(x), end=', ')
    print(']')
    
def list_bin2hex(a: list):
    b = []
    y = 0
    z = 0
    for x in a:
        z = z * 2 + x
        if y % 8 == 7:
            b.append(z) 
            z = 0              
        y = y + 1
    return b

class msg_mode(object):
    '''
    报文分析模式
    表示报文格式的结构
    mode_id: 模式的id号
    mode_name: 模式的名称
    mode_size: 模式的字段数
    mode_datamode: 此位为1则为小端，0为大端，否则根据外部信号进行安排
    '''
    mode_id = 0
    mode_name = ""
    mode_size = 0
    mode = []
    datalen = 0
    mode_datamode = 0
    datalen_name = ""
    next_mode_code = ''
    def __init__(self, modeid: int, modename: str):
        self.mode_id = modeid
        self.mode_size = 0
        self.mode_name = modename
        self.mode = list()
        self.next_mode_list = dict()
    def add_fixed_mode_seg(self, seglen: int, segname: str):
        self.mode.append((0, segname, seglen))
        self.mode_size += 1
    def add_variable_mode_seg(self, seglen_func, segname: str):
        self.mode.append((1, segname, seglen_func))
        self.mode_size += 1
    def set_datalen_name(self, name: str):
        self.datalen_name = name
    def set_data_mode(self, md: int):
        self.mode_datamode = md
    def get_seg_mode(self, segname: str):
        for x, y, z in self.mode:
            if y == segname:
                return (x, y, z)
        return -1
    def set_next_mode_code(self, segname: str):
        self.next_mode_code = segname
    def set_next_mode_list(self, next_list: dict):
        if self.next_mode_code == "-1":
            return
        for x in next_list:
            self.next_mode_list[x] = next_list[x]
        print(self.mode_id, self.next_mode_list)
    def get_mode_id(self):
        return self.mode_id

class msg_segment(object):
    '''
    报文字段：
    报文字段代表的是报文中具有特定含义的一段字段
    比如：IP路段的dst addr字段
    seg_name: 字段名称
    seg_len: 字段长度（byte数）
    seg_data: 报文数据（二进制转为十进制），此处可能还是一个报文，递归分析
    '''
    seg_name = ""
    seg_len = 0
    seg_data = 0x000000
    def __init__(self, name: str, len: int, data):
        self.seg_name = name
        self.seg_len = len
        self.seg_data = data


class msg_struct(object):
    '''
    报文：
    一个完整的报文
    比如一个IP报文
    msg_len: 报文总长度(byte)
    msg_size: 报文的字段数量
    msg_mode_id: 报文类型，此处主要指网络的哪一层，比如网络层
    msg_seg: 报文具体的字段，此处为列表，列表中元素为 msg_segment 类型
    '''
    msg_len = 0
    msg_size = 0
    msg_mode_id = 0
    msg_seg = []
    msg_father = ''
    def __init__(self, len: int, mode_id: int):
        '''
        初始化，只需要报文总类型和报文类型，具体的报文解析在其他函数中
        '''
        self.msg_len = len
        self.msg_size = 0
        self.msg_mode_id = mode_id
        self.msg_seg = list()
        self.msg_data_name = ""
        self.msg_datalen = 0
        self.msg_father = ""
        
    def add_seg(self, seg: msg_segment):
        '''
        添加报文字段
        '''
        self.msg_seg.append(seg)
        self.msg_size += 1
        self.msg_len += seg.seg_len
        # print('%s add seg: %s' % (self.msg_mode_id, seg.seg_name))
        
    def Print(self, dep=0):
        '''
        输出报文分析
        '''
        print("msg: ", self.msg_mode_id)
        print("\t" * dep, end='')
        print("len: %d, size of seg: %d" % (self.msg_len, self.msg_size))
        # print(len(self.msg_seg))
        for seg in self.msg_seg:
            print("\t" * dep, end='')
            print("\tseg_name: %s, seg_len: %d" % (seg.seg_name, seg.seg_len))
            print("\t" * dep, end='')
            print("\tseg data: ")
            print("\t" * (dep + 2), end='')
            if type(seg.seg_data) == msg_struct:
                # print(seg.seg_data)
                seg.seg_data.Print(dep + 1)
            else:
                if type(seg.seg_data) == list:
                    # print(type(seg.seg_data))
                    list_hex_print(list_bin2hex(seg.seg_data))
                else:
                    print(hex(seg.seg_data))

    def set_father(self, father):
        self.msg_father = father
    
    def get_seg(self, name: str):
        for seg in self.msg_seg:
            if seg.seg_name == name:
                return seg
        return -1
    
    def get_seg_data(self, name: str):
        x = self.get_seg(name)
        if x != -1:
            return x.seg_data
        else:
            return -1
        
    def get_msg_len(self):
        return self.msg_len
        
    def get_next_mode(self, now_mode: msg_mode):
        if now_mode.next_mode_code == "-1":
            return 0x00000000
        if now_mode.get_mode_id() == 0xFFFFFFFE or now_mode.next_mode_code == "pcap_header":
            return exchange_dict[now_mode.next_mode_list[now_pcap_LinkType]]
        print(self.get_seg(now_mode.next_mode_code).seg_data)
        return exchange_dict[now_mode.next_mode_list[self.get_seg(now_mode.next_mode_code).seg_data]]

    def set_pcap_LinkType(self):
        global now_pcap_LinkType
        if (self.msg_mode_id == 0xFFFFFFFF):
            now_pcap_LinkType = int(self.get_seg("LinkType").seg_data)
            # print(now_pcap_LinkType)
            # print("lalalalalla")